package org.example.netty.springBoot;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * Netty 客户端
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2021/8/9 15:00
 */
@SuppressWarnings("all")
public class NettyClient {
    private static final Logger log = LoggerFactory.getLogger(NettyClient.class);
    private static final String SERVER_IP = "127.0.0.1";
    private static final int SERVER_PORT = 9308;

    /**
     * 连接 Netty 服务器并发送消息，接收到回复后，自动关闭连接.
     *
     * @param msg ：发送给服务器的消息
     * @return
     */
    public static Map<String, Object> helloNetty(String msg) {
        NettyClientHandler nettyClientHandler = new NettyClientHandler();
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    //TCP_NODELAY：作用是禁止使用 Nagle 算法，用于小数据即时传输.
                    .option(ChannelOption.TCP_NODELAY, true)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        //通道初始化器，设置编码器，解码器，处理器
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast("decoder", new StringDecoder());
                            socketChannel.pipeline().addLast("encoder", new StringEncoder());
                            socketChannel.pipeline().addLast(nettyClientHandler);
                        }
                    });
            ChannelFuture future = bootstrap.connect(SERVER_IP, SERVER_PORT).sync();
            future.channel().writeAndFlush(msg);//发送消息
            log.info("发送消息：{}", msg);
            future.channel().closeFuture().sync();// 等待连接被关闭
        } catch (Exception e) {
            log.error("Netty 连接失败！", e);
            throw new RuntimeException("消息发送失败！", e);
        } finally {
            group.shutdownGracefully();//优雅退出，释放NIO线程组
        }
        return nettyClientHandler.getMsgMap();
    }
}
